package sbc.group1.lab1.alt;

import java.awt.Color;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.concurrent.atomic.AtomicInteger;

import sbc.group1.lab1.common.Car;
import sbc.group1.lab1.common.Engine;
import sbc.group1.lab1.common.Order;
import sbc.group1.lab1.common.Part;
import sbc.group1.lab1.common.Engine.Type;
import sbc.group1.lab1.gui.AbstractFactoryPanel;

class FactoryPanel extends AbstractFactoryPanel {
    //private static final Logger log = LoggerFactory.getLogger(FactoryPanel.class);
    
    private CarService service;
    private final AtomicInteger nextId = new AtomicInteger();
    
    public FactoryPanel(CarService service) throws RemoteException, InterruptedException {
        this.service=service;
        RemoteListener onAdd = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
					FactoryPanel.this.addPart((Part)o);
			}
		};
		
		RemoteListener onRemove = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
				if (o instanceof Part) {
					FactoryPanel.this.removePart((Part)o);
				}
			}
		};
		UnicastRemoteObject.exportObject(onAdd,0);
		UnicastRemoteObject.exportObject(onRemove,0);
		
		service.registerAddListener(onAdd, Containers.BODIES );
		service.registerAddListener(onAdd, Containers.WHEELS );
		service.registerAddListener(onAdd, Containers.ENGINES );
		
		service.registerRemoveListener(onRemove, Containers.BODIES );
		service.registerRemoveListener(onRemove, Containers.WHEELS );
		service.registerRemoveListener(onRemove, Containers.ENGINES );
		
		
		onAdd = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
				Car car = (Car)o;
				if (car.isCoated()) {
					FactoryPanel.this.addCompletedCar(car);
				}else {
					FactoryPanel.this.addAssembledCar(car);
				}
			}
		};
		
		onRemove = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
				Car car = (Car)o;
				if (car.isCoated()) {
					FactoryPanel.this.removeCompleted(car);
				}else {
					FactoryPanel.this.removeAssembled(car);
				}
			}
		};
		UnicastRemoteObject.exportObject(onAdd,0);
		UnicastRemoteObject.exportObject(onRemove,0);
		
		service.registerAddListener(onAdd, Containers.CARS );
		
		service.registerRemoveListener(onRemove, Containers.CARS );
		
		onAdd = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
				Car car = (Car)o;
				if (car.isMarkedAsFinished()) {
					FactoryPanel.this.addFinishedCar(car);
				}
			}
		};
		
		onRemove = new RemoteListener() {
			@Override
			public void onEvent(Object o) throws RemoteException {
				Car car = (Car)o;
				if (car.isMarkedAsFinished()) {
					FactoryPanel.this.removeCompleted(car);
				}
			}
		};
		UnicastRemoteObject.exportObject(onAdd,0);
		UnicastRemoteObject.exportObject(onRemove,0);	
		service.registerAddListener(onAdd, Containers.TOTALFINISHEDCARS );	
		service.registerRemoveListener(onRemove, Containers.TOTALFINISHEDCARS );				

    }
    
    @Override
    protected void asyncProduceCarBodies(int quantity, double relativeDefects) {
        int id = nextId.incrementAndGet();
        Thread t = new Thread(new CarBodyProducer(id, quantity, service, relativeDefects));
        t.setDaemon(true);
        t.start();
    }

    @Override
    protected void asyncProduceEngines(int quantity, double relativeDefects, Engine.Type type) {
        int id = nextId.incrementAndGet();
        Thread t = new Thread(new EngineProducer(id, quantity, service, type,relativeDefects));
        t.setDaemon(true);
        t.start();
    }

    @Override
    protected void asyncProduceWheels(int quantity, double relativeDefects) {
        int id = nextId.incrementAndGet();
        Thread t = new Thread(new WheelProducer(id, quantity, service, relativeDefects));
        t.setDaemon(true);
        t.start();
    }

    @Override
    protected void onNewOrder(int numCars, Type engine, Color coatingColor) {
    	Order o = new Order(numCars, coatingColor, engine);
   	
    	try {
			service.addOrder(o);
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }

}
